package com.kanshu.ksgb.fastread.doudou.common.util;

import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Base64;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
import android.widget.EditText;

import com.kanshu.ksgb.fastread.doudou.app.constants.ARouterConfig;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import io.reactivex.disposables.Disposable;
import retrofit2.Call;

/**
 * 常见工具类
 */
public class Utils {

    /**
     * 判断列表是否为空
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T> boolean isEmptyList(List<T> list) {
        return list == null || list.isEmpty();
    }

    /**
     * 获取元数据
     *
     * @param context
     * @param metaName
     * @return
     */
    public static String getMetaData(Context context, String metaName) {
        String s = null;
        if (context != null) {
            String packageName = context.getPackageName();
            try {
                ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_META_DATA);
                s = applicationInfo.metaData.getString(metaName);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
        }
        return s;
    }

    /**
     * 是否全是数字
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        if (TextUtils.isEmpty(str)) {
            return false;
        }
        for (int i = str.length(); --i >= 0; ) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    private static int sVersionCode = -1;
    private static String sVersionName = "";

    /**
     * 获取版本号
     *
     * @param context
     * @return
     */
    public static int getVersionCode(Context context) {
        if (sVersionCode > 0) {
            return sVersionCode;
        }
        synchronized (context) {
            String localPackageName = context.getPackageName();
            try {
                PackageInfo packageInfo = context.getPackageManager().getPackageInfo(localPackageName, 0);
                return sVersionCode = packageInfo.versionCode;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return -1;
        }
    }

    public static String getVersionName(Context context) {
        if (!TextUtils.isEmpty(sVersionName)) {
            return sVersionName;
        }
        synchronized (context) {
            String localPackageName = context.getPackageName();
            try {
                PackageInfo packageInfo = context.getPackageManager().getPackageInfo(localPackageName, 0);
                return sVersionName = packageInfo.versionName;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    /**
     * 获取进程名
     *
     * @param context
     * @param pid
     * @return
     */
    public static String getProcessName(Context context, int pid) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
        if (runningApps == null) {
            return null;
        }
        for (ActivityManager.RunningAppProcessInfo procInfo : runningApps) {
            if (procInfo.pid == pid) {
                return procInfo.processName;
            }
        }
        return null;
    }

    /**
     * 是否是当前主进程
     *
     * @param context
     * @return
     */
    public static boolean isCurApp(Context context) {
        String packageName = context.getPackageName();
        String processName = getProcessName(context, Process.myPid());
        if (packageName.equals(processName)) {
            return true;
        }
        return false;
    }

    /**
     * rxjava 解除绑定
     *
     * @param disposables
     */
    public static void dispose(List<Disposable> disposables) {
        if (disposables != null) {
            for (Disposable disposable : disposables) {
                dispose(disposable);
            }
            disposables.clear();
        }
    }

    /**
     * rxjava 解除绑定
     *
     * @param disposable
     */
    public static void dispose(Disposable disposable) {
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
    }

    public static void cancelCall(List<Call> calls) {
        if (calls != null) {
            for (Call call : calls) {
                call.cancel();
            }
            calls.clear();
        }
    }

    /**
     * webview后退处理
     *
     * @param webView
     * @return
     */
    public static boolean webviewBack(final WebView webView) {
        if (webView != null) {
            webView.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (event.getAction() == KeyEvent.ACTION_DOWN) {
                        if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {  //表示按返回键
                            webView.goBack();   //后退
                            return true;
                        }
                    }
                    return false;
                }
            });
        }
        return false;
    }

    /**
     * 设置背景
     *
     * @param v
     * @param drawable
     */
    public static void setBackground(View v, Drawable drawable) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            v.setBackground(drawable);
        } else {
            v.setBackgroundDrawable(drawable);
        }
    }

    /**
     * 获取机型
     *
     * @return
     */
    public static String getMachine() {
        return Build.MODEL;
    }


    public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bmp.compress(CompressFormat.PNG, 100, output);
        if (needRecycle) {
            bmp.recycle();
        }

        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * Hides the soft input if it is active for the input text, by  reflection mechanism
     */
    public static void hideSoftKeyboard(EditText edittext) {
        Object o = null;
        try {
            Class<?> threadClazz = Class.forName("android.view.inputmethod.InputMethodManager");

            Method method = threadClazz.getDeclaredMethod("peekInstance");//return sInstance
            Method[] methods = threadClazz.getDeclaredMethods();

            method.setAccessible(true);
            o = method.invoke(null);
            if (o == null) {
                return;
            }
            InputMethodManager inputMethodManager = (InputMethodManager) o;
            if (inputMethodManager != null && inputMethodManager.isActive(edittext)) {
                inputMethodManager.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
            }
        } catch (Exception e) {
        }
    }

    public static void hideSoftKeyboard(Activity activity) {
        if (activity == null || activity.getCurrentFocus() == null) {
            return;
        }
        ((InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE))
                .hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(),
                        InputMethodManager.RESULT_UNCHANGED_SHOWN);
    }

    public static void fixInputMethodManagerLeak(Context destContext) {
        if (destContext == null) {
            return;
        }

        InputMethodManager imm = (InputMethodManager) destContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm == null) {
            return;
        }

        String[] arr = new String[]{"mCurRootView", "mServedView", "mNextServedView"};
        Field f = null;
        Object obj_get = null;
        for (String param : arr) {
            try {
                f = imm.getClass().getDeclaredField(param);
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                } // author: sodino mail:sodino@qq.com
                obj_get = f.get(imm);
                if (obj_get != null && obj_get instanceof View) {
                    View v_get = (View) obj_get;
                    if (v_get.getContext() == destContext) { // 被InputMethodManager持有引用的context是想要目标销毁的
                        f.set(imm, null); // 置空，破坏掉path to gc节点
                    } else {
                        // 不是想要目标销毁的，即为又进了另一层界面了，不要处理，避免影响原逻辑,也就不用继续for循环了
                        break;
                    }
                }
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    }


    public static boolean isSameDay(long time1, long time2) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Date date1 = new Date(time1 * 1000);
        Date date2 = new Date(time2 * 1000);
        String s1 = formatter.format(date1);
        String s2 = formatter.format(date2);
        return s1.equals(s2);
    }


    /**
     * 拼接url
     *
     * @param url
     * @param params
     * @return
     */
    public static String linkUrl(String url, Map<String, String> params) {
        if (params != null) {
            Iterator<String> it = params.keySet().iterator();
            StringBuffer sb = new StringBuffer();
            boolean first = false;
            while (it.hasNext()) {
                String key = it.next();
                String value = params.get(key);
                if (url.contains("?") || first) {
                    sb.append("&");
                } else {
                    sb.append("?");
                    first = true;
                }
                sb.append(key);
                sb.append("=");
                sb.append(value);
            }
            url += sb.toString();
        }
        return url;
    }

    public static void showSoftKeyboard(final EditText et, final int delays) {
        if (et == null)
            return;
        Handler handler = new Handler(Looper.getMainLooper());
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                et.setFocusable(true);
                et.setFocusableInTouchMode(true);
                et.requestFocus();
                InputMethodManager inputManager = (InputMethodManager) et.getContext().getSystemService(
                        Context.INPUT_METHOD_SERVICE);
                inputManager.showSoftInput(et, 0);
            }
        }, delays);

    }

    public static boolean isBackground(Context context) {
        ActivityManager activityManager = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
                .getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(context.getPackageName())) {
                /*
                BACKGROUND=400 EMPTY=500 FOREGROUND=100
                GONE=1000 PERCEPTIBLE=130 SERVICE=300 ISIBLE=200
                 */
                if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        return false;
    }


    public static String bitmapToBase64(Bitmap bitmap) {
        String result = null;
        ByteArrayOutputStream baos = null;
        try {
            if (bitmap != null) {
                baos = new ByteArrayOutputStream();
                bitmap.compress(CompressFormat.PNG, 100, baos);
                baos.flush();
                byte[] bitmapBytes = baos.toByteArray();
                result = "data:image/png;base64," + Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeCloseable(baos);
        }
        return result;
    }

    public static final void closeCloseable(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 去掉空白字符，这里只去掉了尾部的空白字符
     *
     * @param sequence 需处理的字符
     * @return 处理过的字符
     */
    public static CharSequence trimFrom(CharSequence sequence) {
        int len = sequence.length();
        int first = 0;
        int last;

//        for (first = 0; first < len; first++) {
//            if (!matches(sequence.charAt(first))) {
//                break;
//            }
//        }
        for (last = len - 1; last > first; last--) {
            if (!matches(sequence.charAt(last))) {
                break;
            }
        }

        return sequence.subSequence(first, last + 1);
    }

    private static boolean matches(char c) {
        switch (c) {
            case '\t':
            case '\n':
            case '\013':
            case '\f':
            case '\r':
            case ' ':
            case '\u0085':
            case '\u1680':
            case '\u2028':
            case '\u2029':
            case '\u205f':
            case '\u3000':
                return true;
            case '\u2007':
                return false;
            default:
                return c >= '\u2000' && c <= '\u200a';
        }
    }

    public static Bitmap base64ToBitmap(String string) {
        //将字符串转换成Bitmap类型
        Bitmap bitmap = null;
        try {
            byte[] bitmapArray;
            bitmapArray = Base64.decode(string, Base64.DEFAULT);
            bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * 缓存文件存放路径
     *
     * @param context
     * @param uniqueName
     * @return
     */
    public static File getDiskCacheDir(Context context, String uniqueName) {
        if (context == null) {
            return null;
        }
        String cachePath;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                || !Environment.isExternalStorageRemovable()) {
            File cacheDir = context.getExternalCacheDir();
            if (cacheDir != null) {
                cachePath = cacheDir.getPath();
            } else {
                cachePath = Environment.getExternalStorageDirectory().getPath();
            }
        } else {
            cachePath = context.getCacheDir().getPath();
        }
        return new File(cachePath + File.separator + uniqueName);
    }

    public static int getRecyclerScrollDistance(RecyclerView recyclerView) {
        if (recyclerView == null) {
            return 0;
        }
        LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        int position = layoutManager.findFirstVisibleItemPosition();
        View firstVisiableChildView = layoutManager.findViewByPosition(position);
        if (firstVisiableChildView == null) {
            return 0;
        }
        int itemHeight = firstVisiableChildView.getHeight();
        return (position) * itemHeight - firstVisiableChildView.getTop();
    }

    public static String timeStampToDate(String seconds, String format) {
        if (TextUtils.isEmpty(seconds) || seconds.equals("null")) {
            return "";
        }
        if (TextUtils.isEmpty(seconds)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date(Long.valueOf(seconds + "000")));
    }


    public static void fadeIn(View view, long duration) {
        try {
            ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f);
            animator.setDuration(duration);
            animator.start();
        } catch (Exception e) {
        }

    }

    public static boolean isTouchPointInView(View view, int x, int y) {
        if (view == null) {
            return false;
        }
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        int left = location[0];
        int top = location[1];
        int right = left + view.getMeasuredWidth();
        int bottom = top + view.getMeasuredHeight();
        //view.isClickable() &&
        if (y >= top && y <= bottom && x >= left
                && x <= right) {
            return true;
        }
        return false;
    }

    public static void finalizeTimedOut() {
        if (RomUtils.isOppo()) {
            try {
                Class clazz = Class.forName("java.lang.Daemons$FinalizerWatchdogDaemon");
                Method method = clazz.getSuperclass().getDeclaredMethod("stop");
                method.setAccessible(true);
                Field field = clazz.getDeclaredField("INSTANCE");
                field.setAccessible(true);
                method.invoke(field.get(null));
            } catch (Throwable e) {
                e.printStackTrace();
            }

            try {
                Class<?> c = Class.forName("java.lang.Daemons");
                Field maxField = c.getDeclaredField("MAX_FINALIZE_NANOS");
                maxField.setAccessible(true);
                maxField.set(null, Long.MAX_VALUE);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据activity的堆栈情况跳转主页面
     */
    public static void jumpToHomeIfNeed() {
        if (!ActivityMgr.getInstance().existPageByTag(ARouterConfig.PageTagParams.HOME_PAGE)) {
            ARouterUtils.toActivity(ARouterConfig.HOME_PAGE);
        }
    }


    public static void fixHwChangeWindowCtrlLeak() {
        try {
            Class clazz = Class.forName("android.app.HwChangeButtonWindowCtrl");
            Field field = clazz.getDeclaredField("mInstanceMap");
            field.setAccessible(true);
            HashMap hashMap1 = (HashMap) field.get(field.getType().newInstance());
            HashMap h = (HashMap) field.getType().newInstance();
            for (Object key : hashMap1.keySet()) {
                Object o = hashMap1.get(key);
                Object vv = getValueByFieldName(o, "mActivity");
                h.put(key, hashMap1.get(key));
            }
            h.clear();
            field.set(hashMap1, h);
        } catch (Exception e) {

        }
    }

    public static Field getFieldByFieldName(Object obj, String fieldName) {
        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass
                .getSuperclass()) {
            try {
                return superClass.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
            }
        }
        return null;
    }

    public static Object getValueByFieldName(Object obj, String fieldName)
            throws SecurityException, NoSuchFieldException,
            IllegalArgumentException, IllegalAccessException {
        Field field = getFieldByFieldName(obj, fieldName);
        Object value = null;
        if (field != null) {
            if (field.isAccessible()) {
                value = field.get(obj);
            } else {
                field.setAccessible(true);
                value = field.get(obj);
                field.setAccessible(false);
            }
        }
        return value;
    }

    /**
     * unicode转utf8
     * @param src
     * @return
     */
    public static String unicodeToUTF_8(String src) {
        if (TextUtils.isEmpty(src)) {
            return "";
        }
        StringBuilder out = new StringBuilder();
        for (int i = 0; i < src.length(); ) {
            char c = src.charAt(i);
            if (i + 6 < src.length() && c == '\\' && src.charAt(i + 1) == 'u') {
                String hex = src.substring(i + 2, i + 6);
                try {
                    out.append((char) Integer.parseInt(hex, 16));
                } catch (NumberFormatException nfe) {
                    nfe.fillInStackTrace();
                }
                i = i + 6;
            } else {
                out.append(src.charAt(i));
                ++i;
            }
        }
        return out.toString();
    }

    /**
     * 安全的展示用户手机号码
     * @param phone
     * @return
     */
    public static String securityShowPhone(String phone){
        if(!TextUtils.isEmpty(phone) && phone.length() > 10){
            String middle = phone.substring(3,7);
            phone = phone.replace(middle, "xxxx");
        }
        return phone;
    }

    public static void fixTimeoutException() {
        if (RomUtils.isOppo()) {
            try {
                final Class clazz = Class.forName("java.lang.Daemons$FinalizerWatchdogDaemon");
                final Field field = clazz.getDeclaredField("INSTANCE");
                field.setAccessible(true);
                final Object watchdog = field.get(null);
                try {
                    final Field thread = clazz.getSuperclass().getDeclaredField("thread");
                    thread.setAccessible(true);
                    thread.set(watchdog, null);
                } catch (final Throwable t) {

                    t.printStackTrace();
                    try {
                        // 直接调用stop方法，在Android 6.0之前会有线程安全问题
                        final Method method = clazz.getSuperclass().getDeclaredMethod("stop");
                        method.setAccessible(true);
                        method.invoke(watchdog);
                    } catch (final Throwable e) {
                        t.printStackTrace();
                    }
                }
            } catch (final Throwable t) {
                t.printStackTrace();
            }
        }
    }

}
